﻿using Autofac;
using CSRedis;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SH.Common;
using SH.Common.CommonClass;
using SH.Common.CommonReturn;
using SH.Common.DataDictionary;
using SH.Multitenant.Core.Saas;
using SH.Multitenant.Domain.Multitenant;
using SH.Multitenant.Domain.RBAC;
using SH.Multitenant.Infrastructure.IRepository;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace SH.Multitenant.Infrastructure.Repository
{
    public class TenantRepository : ITenantRepository
    {
        private readonly ISqlSugarClient _context;
        private readonly CSRedisClient _redis = AppService.AutofacContainer.Resolve<CSRedisClient>();
        public TenantRepository()
        {
            _context = DbManger.Db;
        }

        //租户添加
        public async Task<ApiResult<int>> TenantAddAsync(TenantDTO tenantInfo)
        {
            ApiResult<int> apiResult = new ApiResult<int>();
            using var tran = _context.AsTenant().UseTran();
            try
            {
                string conn = "";
                //判断是否独立库
                if (tenantInfo.IsSplitDB)
                {
                    conn = $"server=10.31.59.12;database={tenantInfo.TenantId}db;uid=root;pwd=cfy123";
                }
                else
                {
                    conn = AppService.Configuration["ConnectionStrings:TenantDB"];
                }
                #region 信息库添加
                //添加租户信息表TenantInfo
                TenantInfo info = new TenantInfo
                {
                    TenantId = tenantInfo.TenantId,
                    Name = tenantInfo.Name,
                    Tel = tenantInfo.Tel,
                    QQ = tenantInfo.QQ,
                    WeChar = tenantInfo.WeChar,
                    Emails = tenantInfo.Emails,
                    IsSplitDB = tenantInfo.IsSplitDB,
                };
                var result = await _context.Insertable<TenantInfo>(info).ExecuteCommandAsync();
                //判断是否添加成功
                if (result == 0)
                {
                    apiResult.Error(ApiResult<int>.ErrorType.Service, "添加租户信息失败");
                    tran.RollbackTran();
                    return apiResult;
                }
                //添加数据库配置表DbOptions
                result = await _context.Insertable<DbOptions>(new DbOptions
                {
                    Conn = conn,
                    TenantId = tenantInfo.TenantId,
                }).ExecuteCommandAsync();
                //判断是否添加成功
                if (result == 0)
                {
                    apiResult.Error(ApiResult<int>.ErrorType.Service, "添加租户配置失败");
                    tran.RollbackTran();
                    return apiResult;
                }
                //添加租户用户名和密码到用户表
                result = await _context.Insertable<User>(new User
                {
                    //UId = Guid.NewGuid(),
                    UName = tenantInfo.UName,
                    UPwd = tenantInfo.UPwd,
                    TenantId = tenantInfo.TenantId,
                }).ExecuteCommandAsync();
                #endregion
                //List<Type> types = new List<Type>();
                ISqlSugarClient db;

                if (!_context.AsTenant().IsAnyConnection(tenantInfo.TenantId))
                {
                    _context.AsTenant().AddConnection(new ConnectionConfig()
                    {
                        ConfigId = tenantInfo.TenantId,
                        ConnectionString = conn,
                        DbType = DbType.MySql,
                        IsAutoCloseConnection = true,
                        MoreSettings = new ConnMoreSettings
                        {
                            IsAutoDeleteQueryFilter = true,//启用删除查询过滤器  
                            IsAutoUpdateQueryFilter = true//启用更新查询过滤器 （表达式更新，如果是实体方式更新建议先查询在更新）
                        }
                    });
                }
                tran.CommitTran();
                db = _context.AsTenant().GetConnection(tenantInfo.TenantId);
                //如果分库就生成库
                if (tenantInfo.IsSplitDB)
                {
                    db.DbMaintenance.CreateDatabase();
                }
                Type baseType = typeof(Tenant);
                //获取所有的继承基础租户的表
                var types = _redis.HGet<List<Type>>("rbac", "Type");
                if (types == null || types.Count() == 0)
                {
                    types = new List<Type>();
                    var rbacs = Assembly.Load("SH.Multitenant.Domain").GetTypes().Where(t => t.FullName.Contains("RBAC") && t.IsSubclassOf(baseType));
                    //类型存入Redis缓存 DBManager判断类型用 
                    types.AddRange(rbacs);
                    var type = typeof(OperationLog);
                    types.Add(type);
                    _redis.HSet("rbac", "Type", types);
                }
                //先执行 生成库                               
                //如果分表就生成表
                if (tenantInfo.IsSplitDB)
                    db.CodeFirst.InitTables(types.ToArray());
                //var customers = Assembly.Load("SH.Customer.Domain").GetTypes().Where(t => t.FullName.Contains("CustomerClass") && t.IsSubclassOf(baseType));
                //types.AddRange(customers);
                //var orders = Assembly.Load("SH.Order.Domain").GetTypes().Where(t => t.FullName.Contains("OrderClass") && t.IsSubclassOf(baseType));
                //types.AddRange(orders);
                //var rooms = Assembly.Load("SH.Room.Domain").GetTypes().Where(t => t.FullName.Contains("RoomClass") && t.IsSubclassOf(baseType));
                //types.AddRange(rooms);                                       
                //foreach (var item in types)
                //{
                //    var itemData = _context.Queryable<BaseData>().First(x => x.TableName == item.Name).Data;
                //    var dataList = JsonConvert.DeserializeObject(itemData);
                //    var returnResult = await db.InsertableByObject(dataList).ExecuteCommandAsync();
                //    if (returnResult == 0)
                //    {
                //        apiResult.Error(ApiResult<int>.ErrorType.Service, "添加预制信息失败");
                //        tran.RollbackTran();
                //        return apiResult;
                //    }
                //}

                //添加预制数据（从BaseData库表中）
                using var tran1 = db.AsTenant().UseTran();
                try
                {
                    foreach (var item in types)
                    {
                        if (item.Name == "Employee")
                        {
                            result = await db.Insertable<Employee>(new Employee
                            {
                                EmpId = tenantInfo.TenantId + "admin",
                                EmpName = tenantInfo.TenantId + "admin",
                                EmpPwd = tenantInfo.TenantId + "admin",
                                Tel = "233",
                                Email = "admin@qq.com",
                                Gender = false,
                                EntryTime = DateTime.Now,
                                EmpStatus = 0,
                                StoreId = 0,
                                RealName = "admin",
                                TenantId = tenantInfo.TenantId,
                            }).ExecuteCommandAsync();
                        }
                        if (item.Name == "Emp_Role")
                        {
                            result = await db.Insertable<Emp_Role>(new Emp_Role
                            {
                                EmpId = tenantInfo.TenantId + "admin",
                                RoleId = 1,
                                TenantId = tenantInfo.TenantId,
                            }).ExecuteCommandAsync();
                        }
                        if (item.Name == "Role")
                        {
                            result = await db.Insertable<Role>(new Role
                            {

                                RoleName = "超级管理员",
                                CreateTime = DateTime.Now,
                                TenantId = tenantInfo.TenantId,
                            }).ExecuteCommandAsync();
                        }
                        if (item.Name == "Permission")
                        {
                            var permissionList = _context.AsTenant().GetConnection("default").Queryable<Permission>().Where(x => x.TenantId == "default").ToList();
                            //更改租户id
                            foreach (var item1 in permissionList)
                            {
                                item1.TenantId = tenantInfo.TenantId;
                            }
                            //添加权限
                            result = await db.Insertable<Permission>(permissionList).ExecuteCommandAsync();
                        }
                        if (item.Name == "Role_Permission")
                        {
                            var rolePermissionList = _context.AsTenant().GetConnection("default").Queryable<Role_Permission>().Where(x => x.TenantId == "default" && x.RoleId == 1 && !string.IsNullOrEmpty(x.PId)).ToList();
                            foreach (var item1 in rolePermissionList)
                            {
                                item1.TenantId = tenantInfo.TenantId;
                            }
                            //添加角色权限
                            result = await db.Insertable<Role_Permission>(rolePermissionList).ExecuteCommandAsync();
                        }
                    }
                    apiResult.Success();
                    //注册后缓存租户id到redis 方便申请门店时获取租户id
                    _redis.Set("tenantId", info.TenantId);
                    tran1.CommitTran();
                    return apiResult;
                }
                catch (Exception)
                {
                    tran1.RollbackTran();
                    throw;
                }
            }
            catch (Exception)
            {
                tran.RollbackTran();
                throw;
            }
        }
    }


    /// <summary>
    /// 基础信息表
    /// </summary>
    [Tenant("multitenant")]
    public record BaseData
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Id { get; set; }
        public string? TableName { get; set; }
        [SugarColumn(ColumnDataType = "Nvarchar(8000)")]
        public string? Data { get; set; }
        public int HotelType { get; set; }
    }
}
